
matrix orthoProjMatrix;
float3x4 transformMatrix;
float4 elementSize;
float4 strokeWidth;
float4 ellipseParams;
float4 arcParams;
float4 viewportSize;

struct VertexShaderInput
{
	float3 position : POSITION0;
	float4 color : COLOR0;
	float2 texCoord : TEXCOORD0;
};

struct PixelShaderInput
{
	float4 position : POSITION0;
	float2 texCoord : TEXCOORD0;
	float4 color : TEXCOORD1;
};

void VertexMain(in VertexShaderInput vsInput, out PixelShaderInput output)
{
	output = (PixelShaderInput)0;

	float3 newPosTransform = mul(float3(vsInput.position.xy, 1), float3x3(transformMatrix._11_12_13, transformMatrix._21_22_23, transformMatrix._31_32_33));
	newPosTransform.xy /= newPosTransform.z;

	float4 posTransformed = float4(newPosTransform.xy, 0, 1);
	float xbase = -viewportSize.x / 2.0f;
	float ybase = viewportSize.y / 2.0f;
	posTransformed.x += xbase;
	posTransformed.y = ybase - posTransformed.y;

	output.position = mul(float4(posTransformed.xy, 0, 1), orthoProjMatrix);
	output.texCoord = vsInput.texCoord;
	output.color = vsInput.color;
}

float getEllipseRadius(float x, float y)
{
	float phi = atan2(y, x);
	if(phi > arcParams.y || phi < arcParams.x)
		return -1;

	float a2 = ellipseParams.x * ellipseParams.x;
	float b2 = ellipseParams.y * ellipseParams.y;
	float ab = ellipseParams.x * ellipseParams.y;
	float sin2 = sin(phi) * sin(phi);
	float cos2 = cos(phi) * cos(phi);

	return (ab) / sqrt(a2 * sin2 + b2 * cos2);
}

float sinusInterpolate(float src, float dest, float pct)
{
	float sinval = sin(pct * 3.1415926 / 2.0f);
	return sinval * src + (1 - sinval) * dest;
}

void PixelMainFill(in PixelShaderInput input, out float4 color : COLOR0)
{
	float elemX = (-elementSize.x / 2.0f) + elementSize.x * input.texCoord.x;
	float elemY = (-elementSize.y / 2.0f) + elementSize.y * input.texCoord.y;

	float radius = getEllipseRadius(elemX, elemY);
	if(radius < 0)
		color = float4(input.color.rgb, 0);
	else
	{
		float radiusCoord = sqrt(elemX * elemX + elemY * elemY);

		if(radiusCoord <= radius)
			color = input.color;
		else
		{
			float diff = radiusCoord - radius;
			if(diff > 2)
				color = float4(input.color.rgb, 0);
			else
				color = float4(input.color.rgb, sinusInterpolate(input.color.a, 0, 1.0f - diff / 2.0f));
		}
	}
}

void PixelMainDraw(in PixelShaderInput input, out float4 color : COLOR0)
{
	float elemX = (-elementSize.x / 2.0f) + elementSize.x * input.texCoord.x;
	float elemY = (-elementSize.y / 2.0f) + elementSize.y * input.texCoord.y;

	float radius = getEllipseRadius(elemX, elemY);
	if(radius < 0)
		color = float4(input.color.rgb, 0);
	else
	{
		float radiusCoord = sqrt(elemX * elemX + elemY * elemY);

		if(radiusCoord <= radius)
		{
			if((radius - radiusCoord) <= strokeWidth.x)
				color = input.color;
			else
			{
				float diff = (radius - radiusCoord) - strokeWidth.x;
				if(diff > 2)
					color = float4(input.color.rgb, 0);
				else
					color = float4(input.color.rgb, sinusInterpolate(input.color.a, 0, 1.0f - diff / 2.0f));
			}
		}
		else
		{
			float diff = radiusCoord - radius;
			if(diff > 2)
				color = float4(input.color.rgb, 0);
			else
				color = float4(input.color.rgb, sinusInterpolate(input.color.a, 0, 1.0f - diff / 2.0f));
		}
	}
}